function longestIncreasingPath(matrix: number[][]): number {
  const l = matrix.length;
  const r = matrix[0].length;
  const dir = [[0, -1], [1, 0], [0, 1], [-1, 0]];
  const deg: number[] = new Array(l * r).fill(0);
  const to: number[][] = new Array(l * r).fill(null).map(() => []);
  const dist: number[] = new Array(l * r).fill(0);
  const q: number[] = [];
  let ans = 0;
  for (let i = 0; i < l; i++) {
    for (let j = 0; j < r; j++) {
      for (let d = 0; d < 4; d++) {
        const ni = i + dir[d][1];
        const nj = j + dir[d][0];
        if (valid(ni, nj) && matrix[ni][nj] > matrix[i][j]) {
          addEdge(grade(i, j), grade(ni, nj));
        }
      }
    }
  }
  for (let i = 0; i < l * r; i++) {
    if (deg[i] === 0) {
      q.push(i);
      dist[i] = 1;
    }
  }
  while (q.length) {
    const x = q.shift();
    for (let y of to[x]) {
      deg[y]--;
      dist[y] = Math.max(dist[y], dist[x] + 1);
      if (deg[y] === 0) q.push(y);
    }
  }
  for (let i = 0; i < l * r; i++) ans = Math.max(ans, dist[i]);
  return ans;
  function grade(i: number, j: number) {
    return i * r + j;
  };
  function valid(i: number, j: number) {
    return i >= 0 && i < l && j >= 0 && j < r;
  }
  function addEdge(u: number, v: number) {
    deg[v]++;
    to[u].push(v);
  }
};